﻿/*
 * Copyright 2011 Edward L. Stauff.                  Contact: <EdStauff@gmail.com>.
 * 
 * This file, "ReadOnlyDictionary.cs", is part of the "Stauffware.Common" class library.
 * "Stauffware.Common" is free software: you can redistribute it and/or 
 * modify it under the terms of the GNU Lesser Public License as published by the 
 * Free Software Foundation, either version 3 of the License, or (at your option) 
 * any later version.
 * 
 * "Stauffware.Common" is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser Public License for more 
 * details.
 * 
 * You should have received a copy of the GNU Lesser Public License along with 
 * the "Stauffware.Common" sources.  If not, see <http://www.gnu.org/licenses/>.
 */

using System;
using System.Collections;
using System.Collections.Generic;

namespace Stauffware.Common.Core
{
	/// <summary>
	/// Just like System.Collections.Generic.IDictionary, but without the modifying methods.
	/// </summary>
	public interface IReadOnlyDictionary<Tkey, Tvalue> 
		: IEnumerable<KeyValuePair<Tkey, Tvalue>>, IEnumerable
	{
		/// Just like System.Collections.Generic.IDictionary.Keys
		ICollection<Tkey> Keys { get; }

		/// Just like System.Collections.Generic.IDictionary.Values
		ICollection<Tvalue> Values { get; }

		/// Just like System.Collections.Generic.IDictionary.Count
		int Count { get; }

		/// Just like System.Collections.Generic.IDictionary.ContainsKey
		bool ContainsKey (Tkey key);

		/// Just like System.Collections.Generic.IDictionary.TryGetValue
		bool TryGetValue (Tkey key, out Tvalue value);

		/// Just like System.Collections.Generic.IDictionary.this[k]
		Tvalue this[Tkey k] { get; }
	}

	//#################################################################################
	/// <summary>
	/// Read-only wrapper for IDictionary that ensures read-onlyness at compile time.
	/// </summary>
	public class ReadOnlyDictionary<Tkey, Tvalue> : IReadOnlyDictionary<Tkey, Tvalue>
	{
		private readonly IDictionary<Tkey, Tvalue> innerDict;

		/// Just like System.Collections.Generic.IDictionary.Keys
		public ICollection<Tkey> Keys { get { return this.innerDict.Keys; } }

		/// Just like System.Collections.Generic.IDictionary.Values
		public ICollection<Tvalue> Values { get { return this.innerDict.Values; } }

		/// Just like System.Collections.Generic.IDictionary.Count
		public int Count { get { return this.innerDict.Count; } }

		/// Just like System.Collections.Generic.IDictionary.this[k]
		public Tvalue this[Tkey k] { get { return this.innerDict[k]; } }

		/// constructor
		public ReadOnlyDictionary (IDictionary<Tkey, Tvalue> dict)
		{
			Require.NotNull(dict);
			this.innerDict = dict;
		}

		/// Just like System.Collections.Generic.Dictionary.ContainsKey
		public bool ContainsKey (Tkey key)
		{
			return this.innerDict.ContainsKey(key);
		}

		/// Just like System.Collections.Generic.Dictionary.TryGetValue
		public bool TryGetValue (Tkey key, out Tvalue value)
		{
			return this.innerDict.TryGetValue(key, out value);
		}

		/// Just like System.Collections.Generic.IEnumerator.GetEnumerator
		public IEnumerator<KeyValuePair<Tkey, Tvalue>> GetEnumerator ()
		{
			return this.innerDict.GetEnumerator();
		}

		/// Just like System.Collections.IEnumerable.GetEnumerator
		IEnumerator IEnumerable.GetEnumerator ()
		{
			return this.innerDict.GetEnumerator();
		}
	}
}
